home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / PixelMotionBlur / PixelMotionBlur.fx < prev    next >
Encoding:
Text File  |  2004-09-27  |  11.6 KB  |  313 lines

  1. //-----------------------------------------------------------------------------
  2. // File: PixelMotionBlur.fx
  3. //
  4. // Desc: Effect file for image based motion blur. The HLSL shaders are used to
  5. //       calculate the velocity of each pixel based on the last frame's matrix 
  6. //       transforms.  This per-pixel velocity is then used in a blur filter to 
  7. //       create the motion blur effect.
  8. // 
  9. // Copyright (c) Microsoft Corporation. All rights reserved.
  10. //-----------------------------------------------------------------------------
  11.  
  12.  
  13. //-----------------------------------------------------------------------------
  14. // Global variables
  15. //-----------------------------------------------------------------------------
  16. float4 MaterialAmbientColor;
  17. float4 MaterialDiffuseColor;
  18.  
  19. float3 LightDir = normalize(float3(1.0f, 1.0f, 1.0f));
  20. float4 LightAmbient = { 1.0f, 1.0f, 1.0f, 1.0f };    // ambient
  21. float4 LightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f };    // diffuse
  22.  
  23. texture RenderTargetTexture;
  24. texture MeshTexture;
  25. texture CurFrameVelocityTexture;
  26. texture LastFrameVelocityTexture;
  27.  
  28. float4x4 mWorld;
  29. float4x4 mWorldViewProjection;
  30. float4x4 mWorldViewProjectionLast;
  31.  
  32. float PixelBlurConst = 1.0f;
  33. static const float NumberOfPostProcessSamples = 12.0f;
  34. float ConvertToNonHomogeneous;
  35. float VelocityCapSq = 1.0f;
  36. float RenderTargetWidth;
  37. float RenderTargetHeight;
  38.  
  39.  
  40. //-----------------------------------------------------------------------------
  41. // Texture samplers
  42. //-----------------------------------------------------------------------------
  43. sampler RenderTargetSampler = 
  44. sampler_state
  45. {
  46.     Texture = <RenderTargetTexture>;
  47.     MinFilter = POINT;  
  48.     MagFilter = POINT;
  49.  
  50.     AddressU = Clamp;
  51.     AddressV = Clamp;
  52. };
  53.  
  54. sampler CurFramePixelVelSampler = 
  55. sampler_state
  56. {
  57.     Texture = <CurFrameVelocityTexture>;
  58.     MinFilter = POINT;
  59.     MagFilter = POINT;
  60.  
  61.     AddressU = Clamp;
  62.     AddressV = Clamp;
  63. };
  64.  
  65. sampler LastFramePixelVelSampler = 
  66. sampler_state
  67. {
  68.     Texture = <LastFrameVelocityTexture>;
  69.     MinFilter = POINT;
  70.     MagFilter = POINT;
  71.  
  72.     AddressU = Clamp;
  73.     AddressV = Clamp;
  74. };
  75.  
  76. sampler MeshTextureSampler = 
  77. sampler_state
  78. {
  79.     Texture = <MeshTexture>;
  80.     MipFilter = LINEAR;
  81.     MinFilter = LINEAR;
  82.     MagFilter = LINEAR;
  83. };
  84.  
  85.  
  86. //-----------------------------------------------------------------------------
  87. // Vertex shader output structure
  88. //-----------------------------------------------------------------------------
  89. struct VS_OUTPUT
  90. {
  91.     float4 Position : POSITION;   // position of the vertex
  92.     float4 Diffuse  : COLOR0;     // diffuse color of the vertex
  93.     float2 TextureUV : TEXCOORD0;  // typical texture coords stored here
  94.     float2 VelocityUV : TEXCOORD1;  // per-vertex velocity stored here
  95. };
  96.  
  97.  
  98. //-----------------------------------------------------------------------------
  99. // Name: WorldVertexShader     
  100. // Type: Vertex shader                                      
  101. // Desc: In addition to standard transform and lighting, it calculates the velocity 
  102. //       of the vertex and outputs this as a texture coord.
  103. //-----------------------------------------------------------------------------
  104. VS_OUTPUT WorldVertexShader( float4 vPos : POSITION, 
  105.                              float3 vNormal : NORMAL,
  106.                              float2 vTexCoord0 : TEXCOORD0 )
  107. {
  108.     VS_OUTPUT Output;
  109.     float3 vNormalWorldSpace;
  110.     float4 vPosProjSpaceCurrent; 
  111.     float4 vPosProjSpaceLast; 
  112.   
  113.     vNormalWorldSpace = normalize(mul(vNormal, (float3x3)mWorld)); // normal (world space)
  114.     
  115.     // Transform from object space to homogeneous projection space
  116.     vPosProjSpaceCurrent = mul(vPos, mWorldViewProjection);
  117.     vPosProjSpaceLast = mul(vPos, mWorldViewProjectionLast);
  118.     
  119.     // Output the vetrex position in projection space
  120.     Output.Position = vPosProjSpaceCurrent;
  121.  
  122.     // Convert to non-homogeneous points [-1,1] by dividing by w 
  123.     vPosProjSpaceCurrent /= vPosProjSpaceCurrent.w;
  124.     vPosProjSpaceLast /= vPosProjSpaceLast.w;
  125.     
  126.     // Vertex's velocity (in non-homogeneous projection space) is the position this frame minus 
  127.     // its position last frame.  This information is stored in a texture coord.  The pixel shader 
  128.     // will read the texture coordinate with a sampler and use it to output each pixel's velocity.
  129.     float2 velocity = vPosProjSpaceCurrent - vPosProjSpaceLast;    
  130.     
  131.     // The velocity is now between (-2,2) so divide by 2 to get it to (-1,1)
  132.     velocity /= 2.0f;   
  133.  
  134.     // Store the velocity in a texture coord
  135.     Output.VelocityUV = velocity;
  136.         
  137.     // Compute simple lighting equation
  138.     Output.Diffuse.rgb = MaterialDiffuseColor * LightDiffuse * max(0,dot(vNormalWorldSpace, LightDir)) + 
  139.                          MaterialAmbientColor * LightAmbient;   
  140.     Output.Diffuse.a = 1.0f; 
  141.     
  142.     // Just copy the texture coordinate through
  143.     Output.TextureUV = vTexCoord0; 
  144.     
  145.     return Output;    
  146. }
  147.  
  148.  
  149. //-----------------------------------------------------------------------------
  150. // Pixel shader output structure
  151. //-----------------------------------------------------------------------------
  152. struct PS_OUTPUT
  153. {
  154.     // The pixel shader can output 2+ values simulatanously if 
  155.     // d3dcaps.NumSimultaneousRTs > 1
  156.     
  157.     float4 RGBColor      : COLOR0;  // Pixel color    
  158.     float4 PixelVelocity : COLOR1;  // Pixel velocity 
  159. };
  160.  
  161.  
  162. //-----------------------------------------------------------------------------
  163. // Name: WorldPixelShader                                        
  164. // Type: Pixel shader
  165. // Desc: Uses multiple render targets (MRT) to output 2 values at once from a 
  166. //       pixel shader.  This shader outputs the pixel's color and velocity.
  167. //-----------------------------------------------------------------------------
  168. PS_OUTPUT WorldPixelShader( VS_OUTPUT In )
  169.     PS_OUTPUT Output;
  170.  
  171.     // Lookup mesh texture and modulate it with diffuse
  172.     Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV) * In.Diffuse;
  173.  
  174.     // Velocity of this pixel simply equals the linear interpolation of the 
  175.     // velocity of this triangle's vertices.  The interpolation is done
  176.     // automatically since the velocity is stored in a texture coord.
  177.     // We're storing the velocity in .R & .G channels and the app creates 
  178.     // a D3DFMT_G16R16F texture to store this info in high precison.
  179.     Output.PixelVelocity = float4(In.VelocityUV,1.0f,1.0f);
  180.     
  181.     // Using MRT, output 2 values in the pixel shader.    
  182.     return Output;
  183. }
  184.  
  185.  
  186. float4 WorldPixelShaderColor( float4 Diffuse : COLOR0,
  187.                               float2 TextureUV : TEXCOORD0 ) : COLOR0
  188.     // Lookup mesh texture and modulate it with diffuse
  189.     return tex2D( MeshTextureSampler, TextureUV ) * Diffuse;
  190. }
  191.  
  192.  
  193. float4 WorldPixelShaderVelocity( float2 VelocityUV : TEXCOORD1 ) : COLOR0
  194.     // Velocity of this pixel simply equals the linear interpolation of the 
  195.     // velocity of this triangle's vertices.  The interpolation is done
  196.     // automatically since the velocity is stored in a texture coord.
  197.     // We're storing the velocity in .R & .G channels and the app creates 
  198.     // a D3DFMT_G16R16F texture to store this info in high precison.
  199.     return float4( VelocityUV, 1.0f, 1.0f );
  200. }
  201.  
  202.  
  203. //-----------------------------------------------------------------------------
  204. // Name: PostProcessMotionBlurPS 
  205. // Type: Pixel shader                                      
  206. // Desc: Uses the pixel's velocity to sum up and average pixel in that direction
  207. //       to create a blur effect based on the velocity in a fullscreen
  208. //       post process pass.
  209. //-----------------------------------------------------------------------------
  210. float4 PostProcessMotionBlurPS( float2 OriginalUV : TEXCOORD0 ) : COLOR
  211. {
  212.     float2 pixelVelocity;
  213.     
  214.     // Get this pixel's current velocity and this pixel's last frame velocity
  215.     // The velocity is stored in .r & .g channels
  216.     float4 curFramePixelVelocity = tex2D(CurFramePixelVelSampler, OriginalUV);
  217.     float4 lastFramePixelVelocity = tex2D(LastFramePixelVelSampler, OriginalUV);
  218.  
  219.     // If this pixel's current velocity is zero, then use its last frame velocity
  220.     // otherwise use its current velocity.  We don't want to add them because then 
  221.     // you would get double the current velocity in the center.  
  222.     // If you just use the current velocity, then it won't blur where the object 
  223.     // was last frame because the current velocity at that point would be 0.  Instead 
  224.     // you could do a filter to find if any neighbors are non-zero, but that requires a lot 
  225.     // of texture lookups which are limited and also may not work if the object moved too 
  226.     // far, but could be done multi-pass.
  227.     float curVelocitySqMag = curFramePixelVelocity.r * curFramePixelVelocity.r +
  228.                              curFramePixelVelocity.g * curFramePixelVelocity.g;
  229.     float lastVelocitySqMag = lastFramePixelVelocity.r * lastFramePixelVelocity.r +
  230.                               lastFramePixelVelocity.g * lastFramePixelVelocity.g;
  231.                                    
  232.     if( lastVelocitySqMag > curVelocitySqMag )
  233.     {
  234.         pixelVelocity.x =  lastFramePixelVelocity.r * PixelBlurConst;   
  235.         pixelVelocity.y = -lastFramePixelVelocity.g * PixelBlurConst;
  236.     }
  237.     else
  238.     {
  239.         pixelVelocity.x =  curFramePixelVelocity.r * PixelBlurConst;   
  240.         pixelVelocity.y = -curFramePixelVelocity.g * PixelBlurConst;    
  241.     }
  242.     
  243.     // For each sample, sum up each sample's color in "Blurred" and then divide
  244.     // to average the color after all the samples are added.
  245.     float3 Blurred = 0;    
  246.     for(float i = 0; i < NumberOfPostProcessSamples; i++)
  247.     {   
  248.         // Sample texture in a new spot based on pixelVelocity vector 
  249.         // and average it with the other samples        
  250.         float2 lookup = pixelVelocity * i / NumberOfPostProcessSamples + OriginalUV;
  251.         
  252.         // Lookup the color at this new spot
  253.         float4 Current = tex2D(RenderTargetSampler, lookup);
  254.         
  255.         // Add it with the other samples
  256.         Blurred += Current.rgb;
  257.     }
  258.     
  259.     // Return the average color of all the samples
  260.     return float4(Blurred / NumberOfPostProcessSamples, 1.0f);
  261. }
  262.  
  263.  
  264. //-----------------------------------------------------------------------------
  265. // Name: WorldWithVelocityMRT
  266. // Type: Technique                                     
  267. // Desc: Renders the scene's color to render target 0 and simultaneously writes 
  268. //       pixel velocity to render target 1.
  269. //-----------------------------------------------------------------------------
  270. technique WorldWithVelocityMRT
  271. {
  272.     pass P0
  273.     {          
  274.         VertexShader = compile vs_2_0 WorldVertexShader();
  275.         PixelShader  = compile ps_2_0 WorldPixelShader();
  276.     }
  277. }
  278.  
  279.  
  280. technique WorldWithVelocityTwoPasses
  281. {
  282.     pass P0
  283.     {
  284.         VertexShader = compile vs_2_0 WorldVertexShader();
  285.         PixelShader  = compile ps_2_0 WorldPixelShaderColor();
  286.     }
  287.     pass P1
  288.     {
  289.         VertexShader = compile vs_2_0 WorldVertexShader();
  290.         PixelShader  = compile ps_2_0 WorldPixelShaderVelocity();
  291.     }
  292. }
  293.  
  294.  
  295. //-----------------------------------------------------------------------------
  296. // Name: PostProcessMotionBlur
  297. // Type: Technique                                     
  298. // Desc: Renders a full screen quad and uses velocity information stored in 
  299. //       the textures to blur image.
  300. //-----------------------------------------------------------------------------
  301. technique PostProcessMotionBlur
  302. {
  303.     pass P0
  304.     {        
  305.         PixelShader = compile ps_2_0 PostProcessMotionBlurPS();
  306.     }
  307. }
  308.  
  309.  
  310.